package com.sc.byahi.user.server;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.sc.byahi.user.shared.Profile;
import com.sc.byahi.user.shared.SharedUtil;
import com.sc.byahi.user.shared.constants.Config;

public class Upload extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private static Logger logger = Logger.getLogger("com.sc.byahi.user.server.Upload");

	public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		UserService userService = UserServiceFactory.getUserService();
		User user = userService.getCurrentUser();
		logger.log(Level.WARNING, "Upload method called by user: " + user);
		if (StoreUtil.DEV_MODE || Config.bulkTestUpload) {
			String email = req.getParameter("email");
			user = new User(email, "byahi.com");
		}
		String profileId = req.getParameter("profileid");
		Long pId = SharedUtil.getLong(profileId);

		if (pId != null) {
			DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
			try {
				Entity p = datastore.get(KeyFactory.createKey(Profile.class.getSimpleName(), pId));
				String owner = (String) p.getProperty(Profile.OWNER);
				if (owner.equals(user.getEmail()) || userService.isUserAdmin()) {
					List<BlobKey> uploadedBlobKeys = StoreUtil.getUploadedBlobs(req);
					List<BlobKey> response = StoreUtil.resizeAndUploadImages(uploadedBlobKeys, profileId);
					StoreUtil.replaceProfileImages(response, datastore, p);
				}
			} catch (EntityNotFoundException e) {
				logger.log(Level.SEVERE, "Entity not found for id:" + pId);
				res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
				res.flushBuffer();
			}
		}

		res.setStatus(HttpServletResponse.SC_OK);
		res.flushBuffer();
	}

	/*
	 * @Deprecated private int saveResizedImage(Collection<BlobKey> blobKey, String profileId) { PrintWriter writer = null; int responseCode =
	 * HttpURLConnection.HTTP_INTERNAL_ERROR; try { Map<BlobKey, byte[]> imageData = new HashMap<BlobKey, byte[]>(); ImagesService imagesService =
	 * ImagesServiceFactory.getImagesService(); int height = 500; int width = 500; for (BlobKey blobKey2 : blobKey) { Image oldImage =
	 * ImagesServiceFactory.makeImageFromBlob(blobKey2); Transform resize = ImagesServiceFactory.makeResize(height, width); Image newImage =
	 * imagesService.applyTransform(resize, oldImage, new OutputSettings(OutputEncoding.JPEG)); byte[] imageFile = newImage.getImageData();
	 * imageData.put(blobKey2, imageFile); }
	 * 
	 * String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value. String CRLF = "\r\n"; // Line
	 * separator required by multipart/form-data.
	 * 
	 * BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService(); // String url =
	 * blobstoreService.createUploadUrl("/user/upload"); String url = blobstoreService.createUploadUrl("/public/resizeupolad"); String charset =
	 * "UTF-8"; URLConnection connection = new URL(url).openConnection(); connection.setDoOutput(true); ((HttpURLConnection)
	 * connection).setRequestMethod("POST"); ((HttpURLConnection) connection).setReadTimeout(5 * 60 * 1000);
	 * connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
	 * 
	 * OutputStream output = connection.getOutputStream(); writer = new PrintWriter(new OutputStreamWriter(output, charset), true); // true =
	 * autoFlush, important!
	 * 
	 * writer.append("--" + boundary).append(CRLF); writer.append("Content-Disposition: form-data; name=\"profileid\"").append(CRLF);
	 * writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF); writer.append(CRLF); writer.append(profileId).append(CRLF).flush();
	 * 
	 * int counter = 0; for (BlobKey blobKey2 : blobKey) { counter++; byte[] data = imageData.get(blobKey2);
	 * 
	 * // Send image file. writer.append("--" + boundary).append(CRLF); writer.append("Content-Disposition: form-data; name=\"photo" + counter +
	 * "\"; filename=\"photo" + counter + "\"").append(CRLF); // writer.append("Content-Type: image/jpeg; charset=" + charset).append(CRLF);
	 * writer.append("Content-Type: image/jpeg").append(CRLF); writer.append(CRLF).flush(); BufferedReader reader = null; try { reader = new
	 * BufferedReader(new InputStreamReader(new ByteArrayInputStream(data), charset)); for (String line; (line = reader.readLine()) != null;) {
	 * writer.append(line).append(CRLF); } } finally { if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) { } }
	 * writer.flush(); }
	 * 
	 * // End of multipart/form-data. writer.append("--" + boundary + "--").append(CRLF); if (writer != null) writer.close(); responseCode =
	 * ((HttpURLConnection) connection).getResponseCode(); logger.log(Level.FINE, "Resize Image Submit responseCode:" + responseCode); } catch
	 * (Exception e) { logger.log(Level.SEVERE, "Exception:", e); } return responseCode; }
	 * 
	 * @SuppressWarnings("unchecked")
	 * 
	 * @Deprecated public void doPost1(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String profileId =
	 * req.getParameter("profileid"); Long pId = Util.getLong(profileId); if (pId != null) { try { DatastoreService datastore =
	 * DatastoreServiceFactory.getDatastoreService(); Entity p = datastore.get(KeyFactory.createKey(Profile.class.getSimpleName(), pId)); String owner
	 * = (String) p.getProperty("owner"); UserService userService = UserServiceFactory.getUserService(); User user = userService.getCurrentUser(); if
	 * (!Util.appEngine) { String email = req.getParameter("email"); user = new User(email, "test.com"); } if (owner.equals(user.getEmail()) ||
	 * userService.isUserAdmin()) {
	 * 
	 * BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService(); Map<String, BlobKey> blobs =
	 * blobstoreService.getUploadedBlobs(req); if (blobs.size() > 0) { // Delete old photos now // Null and empty collections are ignored by App
	 * Engine List<String> oldImages = new ArrayList<String>(4); Object imagesObj = p.getProperty("images"); if (imagesObj != null) {
	 * oldImages.addAll((List<String>) imagesObj); } for (String key : oldImages) { BlobKey oldImageBlobKey = new BlobKey(key); try {
	 * System.out.println("deleting: " + oldImageBlobKey.toString()); blobstoreService.delete(oldImageBlobKey); } catch (BlobstoreFailureException
	 * bfe) { logger.log(Level.SEVERE, "Error while deleting Blobkey: " + oldImageBlobKey.toString(), bfe); } }
	 * 
	 * List<String> newImages = new ArrayList<String>(4); for (BlobKey key : blobs.values()) { System.out.println("saving: " + key.toString());
	 * newImages.add(key.getKeyString()); } p.setProperty("images", newImages); p.setProperty("approved", false); datastore.put(p);
	 * 
	 * // Now profile is saved in datastore, call upload again with resized data and delete old data as usual String resized =
	 * req.getParameter("resized"); if (resized == null || "".equals(resized)) { // saveResizedImage(blobs.values(), profileId, user.getEmail()); }
	 * 
	 * } }
	 * 
	 * } catch (EntityNotFoundException e) { logger.log(Level.SEVERE, "Entity not ound while uploading picture:" + profileId); } }
	 * 
	 * res.setStatus(HttpServletResponse.SC_OK); res.flushBuffer();
	 * 
	 * }
	 * 
	 * @Deprecated private BlobKey resizeAndWriteImageToBlob0(BlobKey blobKey) { try { ImagesService imagesService =
	 * ImagesServiceFactory.getImagesService(); Image oldImage = ImagesServiceFactory.makeImageFromBlob(blobKey); int height = 500; int width = 500;
	 * 
	 * Transform resize = ImagesServiceFactory.makeResize(height, width); Image newImage = imagesService.applyTransform(resize, oldImage, new
	 * OutputSettings(OutputEncoding.JPEG)); byte[] bytes = newImage.getImageData();
	 * 
	 * FileService fileService = FileServiceFactory.getFileService(); AppEngineFile file = fileService.createNewBlobFile("image/jpeg");
	 * 
	 * FileWriteChannel writeChannel = fileService.openWriteChannel(file, true); OutputStream out = Channels.newOutputStream(writeChannel);
	 * out.write(bytes); out.flush(); writeChannel.closeFinally(); BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
	 * blobstoreService.delete(blobKey); return fileService.getBlobKey(file); } catch (Exception e) { e.printStackTrace(); } return null; }
	 * 
	 * @Deprecated private void resizeAndWriteImageToBlob(BlobKey blobKey, String profileId) { try { ImagesService imagesService =
	 * ImagesServiceFactory.getImagesService(); Image oldImage = ImagesServiceFactory.makeImageFromBlob(blobKey); int height = 500; int width = 500;
	 * 
	 * Transform resize = ImagesServiceFactory.makeResize(height, width); Image newImage = imagesService.applyTransform(resize, oldImage, new
	 * OutputSettings(OutputEncoding.JPEG)); byte[] bytes = newImage.getImageData();
	 * 
	 * String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value. String CRLF = "\r\n"; // Line
	 * separator required by multipart/form-data.
	 * 
	 * BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService(); // String url =
	 * blobstoreService.createUploadUrl("/user/upload?profileid="+profileId+"&resized=true"); String url =
	 * blobstoreService.createUploadUrl("/user/upload"); url = url + "?profileid=" + profileId + "&oldBlobKey=" + blobKey.getKeyString();
	 * 
	 * URLConnection connection = new URL(url).openConnection(); connection.setDoOutput(true); connection.setRequestProperty("Content-Type",
	 * "multipart/form-data; boundary=" + boundary); PrintWriter writer = null; try { OutputStream output = connection.getOutputStream(); writer = new
	 * PrintWriter(new OutputStreamWriter(output, "UTF-8"), true); // true = autoFlush, important!
	 * 
	 * // Send normal param. // writer.append("--" + boundary).append(CRLF); //
	 * writer.append("Content-Disposition: form-data; name=\"profileid\"").append(CRLF); // writer.append("Content-Type: text/plain; charset=" +
	 * "utf-8").append(CRLF); // writer.append(CRLF); // writer.append(profileId).append(CRLF).flush();
	 * 
	 * // Send normal param. // writer.append("--" + boundary).append(CRLF); //
	 * writer.append("Content-Disposition: form-data; name=\"resized\"").append(CRLF); // writer.append("Content-Type: text/plain; charset=" +
	 * "utf-8").append(CRLF); // writer.append(CRLF); // writer.append("true").append(CRLF).flush();
	 * 
	 * // Send binary file. writer.append("--" + boundary).append(CRLF);
	 * writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + "photo" + "\"").append(CRLF); writer.append("Content-Type: "
	 * + "image/jpeg").append(CRLF); writer.append("Content-Transfer-Encoding: binary").append(CRLF); writer.append(CRLF).flush(); InputStream input =
	 * null; try { output.write(bytes); output.flush(); // Important! Output cannot be closed. Close of writer will close output as well. } finally {
	 * if (input != null) try { input.close(); } catch (IOException logOrIgnore) { } } writer.append(CRLF).flush(); // CRLF is important! It indicates
	 * end of binary boundary.
	 * 
	 * // End of multipart/form-data. writer.append("--" + boundary + "--").append(CRLF); } finally { if (writer != null) writer.close(); }
	 * 
	 * InputStream response = connection.getInputStream(); int status = ((HttpURLConnection) connection).getResponseCode(); for (Entry<String,
	 * List<String>> header : connection.getHeaderFields().entrySet()) { System.out.println(header.getKey() + "=" + header.getValue()); }
	 * 
	 * } catch (Exception e) { e.printStackTrace(); } }
	 * 
	 * @Deprecated private byte[] readImages(BlobKey blobKey) throws Exception { FileService fileService = FileServiceFactory.getFileService();
	 * AppEngineFile file = fileService.getBlobFile(blobKey); FileReadChannel readChannel = fileService.openReadChannel(file, false); InputStream
	 * reader = Channels.newInputStream(readChannel); byte[] bytes = new byte[reader.available()]; reader.read(bytes); readChannel.close(); return
	 * bytes; }
	 */
	/*
	 * private BlobKey clickOnNose(BlobKey blobKey, double ) { try { ImagesService imagesService = ImagesServiceFactory.getImagesService(); Image
	 * oldImage = ImagesServiceFactory.makeImageFromBlob(blobKey);
	 * 
	 * Transform resize = ImagesServiceFactory.makeCrop(leftX, topY, rightX, bottomY);
	 * 
	 * int height = 150; int width = 150;
	 * 
	 * 
	 * Transform resize = ImagesServiceFactory.makeResize(height, width); Image newImage = imagesService.applyTransform(resize, oldImage,new
	 * OutputSettings(OutputEncoding.JPEG)); byte[] bytes = newImage.getImageData(); FileService fileService = FileServiceFactory.getFileService();
	 * AppEngineFile file = fileService.createNewBlobFile("image/jpeg"); FileWriteChannel writeChannel = fileService.openWriteChannel(file, true);
	 * OutputStream out = Channels.newOutputStream(writeChannel); out.write(bytes); writeChannel.closeFinally(); BlobstoreService blobstoreService =
	 * BlobstoreServiceFactory.getBlobstoreService(); blobstoreService.delete(blobKey); return fileService.getBlobKey(file); } catch (Exception e) {
	 * e.printStackTrace(); } return null; }
	 * 
	 * 
	 * 
	 * Image newImage = imagesService.applyTransform(resize, oldImage);
	 * 
	 * byte[] newImageData = newImage.getImageData();
	 */
	/*
	 * for (int i = 0; i < blobs.size(); i++) { BlobKey blobKey = blobs.get("photo" + (i + 1)); // BlobKey newBlobKey = null;//not resizing anymore
	 * BlobKey newBlobKey = resizeAndWriteImageToBlob(blobKey, profileId); if(newBlobKey != null) profile.addImagesBlobKey(newBlobKey.getKeyString());
	 * else profile.addImagesBlobKey(blobKey.getKeyString()); }
	 */
}
